package com.bupt.server.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bupt.server.entity.Record;
import com.bupt.server.entity.Room;
import com.bupt.server.obj.PublicData;
import com.bupt.server.obj.ACManager;
import com.bupt.server.ret.Data;
import com.bupt.server.serviceImpl.RoomServiceImpl;
import com.bupt.server.serviceImpl.ServiceRecordServiceImpl;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.element.Paragraph;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.swing.text.Document;
import java.io.*;

@RestController
@RequestMapping("/user")
public class RoomController {

    @Autowired
    ServiceRecordServiceImpl serviceRecordService;

    @Autowired
    RoomServiceImpl roomService;


    //todo：完成了
    @PostMapping("/enter_room")
    String enterRoom(@RequestBody String data_string){
        System.out.println("receive msg:"+data_string);
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        Room room;
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(data.getRoom_id());
            if(room!=null) {
                room.setRequest_time(ACManager.currtimer);
                code = 200;
                msg = "success";
                jObject.put("code", code);
                jObject.put("msg", msg);
                return jObject.toJSONString();
            }else{
                code = 400;
                msg = "fail";
                jObject.put("code", code);
                jObject.put("msg", msg);
                return jObject.toJSONString();
            }
        }
    }

    //todo：完成了
    @PostMapping("/info")
    String checkRoomInfo(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        Room room;
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(data.getRoom_id());
        }
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        JSONObject dataObject = new JSONObject();
        if(room != null){
            code = 200;
            msg = "success";
            dataObject.put("status",room.getAc_status());
            dataObject.put("target_temp",room.getTarget_temperature());
            dataObject.put("current_temp",room.getCurrent_temperature());
            dataObject.put("speed",room.getSpeed());
            dataObject.put("cost",room.getTotal_air_cost());// cost指的是空调的情况
            dataObject.put("mode",room.getMode());
            jObject.put("code", code);
            jObject.put("data", dataObject);
            jObject.put("msg", msg);
            return jObject.toJSONString();
        }else{
            code = 400;
            msg = "fail";
            jObject.put("code", code);
            jObject.put("data", dataObject);
            jObject.put("msg", msg);
            return jObject.toJSONString();
        }
    }


    //todo：完成了
    @PostMapping("/set_speed")
    String setRoomSpeed(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        int updateResult = roomService.updateRoomSpeed(data);
        synchronized (PublicData.class) {
            PublicData.totalRoomList.get(data.getRoom_id()).setSpeed(data.getSpeed());
        }
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        if(updateResult > 0){
            code = 200;
            msg = "success";
        }else{
            code = 400;
            msg = "fail";
        }
        jObject.put("code", code);
        jObject.put("msg", msg);
        return jObject.toJSONString();
    }

    //todo：完成了
    @PostMapping("/set_temp")
    String setRoomTargetTemp(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        int updateResult = roomService.updateRoomTargetTemp(data);
        synchronized (PublicData.class) {
            PublicData.totalRoomList.get(data.getRoom_id()).setTarget_temperature(data.getTemp());
            PublicData.totalRoomList.get(data.getRoom_id()).setTarget_temperature(data.getTemp());
        }
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        if(updateResult > 0){
            code = 200;
            msg = "success";
        }else{
            code = 400;
            msg = "fail";
        }
        jObject.put("code", code);
        jObject.put("msg", msg);
        return jObject.toJSONString();
    }

    //todo：完成了
    @PostMapping("/request_service")
    String openAC(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        Room room;
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(data.getRoom_id());
        }
        if(PublicData.temp.equals("heat")) {
            room.setAc_status("on");
            room.setSpeed("medium");
            room.setTarget_temperature(room.getTarget_temperature());
        }else{
            room.setAc_status("on");
            room.setSpeed("medium");
            room.setTarget_temperature(room.getTarget_temperature());
        }
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        JSONObject dataObject = new JSONObject();
        if(room != null){
            code = 200;
            msg = "success";
            dataObject.put("status",room.getAc_status());
            dataObject.put("target_temp",room.getTarget_temperature());
            dataObject.put("current_temp",room.getCurrent_temperature());
            dataObject.put("speed",room.getSpeed());
            dataObject.put("cost",room.getTotal_air_cost());// cost指的是空调的情况
            dataObject.put("mode",room.getMode());
            jObject.put("code", code);
            jObject.put("data", dataObject);
            jObject.put("msg", msg);
            return jObject.toJSONString();
        }else{
            code = 400;
            msg = "fail";
            jObject.put("code", code);
            jObject.put("data", dataObject);
            jObject.put("msg", msg);
            return jObject.toJSONString();
        }
    }

    //todo：完成
    @PostMapping("/pause_service")
    String pauseService(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        Room room;
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(data.getRoom_id());
        }
        room.setAc_status("off");
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        if(room != null){
            code = 200;
            msg = "success";
        }else{
            code = 400;
            msg = "fail";
        }
        jObject.put("code", code);
        jObject.put("msg", msg);
        return jObject.toJSONString();
    }


    // todo：quit_room接口,如果没有要求这个接口删了
    @PostMapping("/quit_room")
    String quit(@RequestBody String data_string){
        JSONObject jsonObject = JSON.parseObject(data_string);
        JSONObject dataJson = jsonObject.getJSONObject("data");
        Data data = dataJson.toJavaObject(Data.class);
        Room room;
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(data.getRoom_id());
            /*
            if(room!=null) {
                room.setStatus(false);
                room.setEnd_time(ReadFile.currtimer);
            }
            */
        }
        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        if(room != null){
            code = 200;
            msg = "success";
            jObject.put("code", code);
            jObject.put("msg", msg);
            //todo:退房时输出账单
            return jObject.toJSONString();
        }else{
            code = 400;
            msg = "fail";
            jObject.put("code", code);
            jObject.put("msg", msg);
            return jObject.toJSONString();
        }
    }

    @PostMapping("/ac_control")
    String acControl(@RequestBody String data_string) {
        JSONObject jsonObject = JSONObject.parseObject(data_string);
        String control = jsonObject.getString("control");
        synchronized (PublicData.class){
            PublicData.temp = control;
            for (Integer key : PublicData.totalRoomList.keySet()) {
                PublicData.resetRoom(control,key);
            }
        }

        int code;
        String msg;
        JSONObject jObject = new JSONObject();
        code = 200;
        msg = "success";
        jObject.put("code", code);
        jObject.put("msg", msg);
        return jObject.toJSONString();
    }

    @PostMapping("/room_list_info")
    String getAllRoomStatus() {
        JSONArray jsonArray = new JSONArray();
        synchronized (PublicData.class) {
            for (Room room : PublicData.totalRoomList.values()) {
                JSONObject roomJson = new JSONObject();
                roomJson.put("room_id", room.getRoom_id());
                roomJson.put("status", room.isStatus());
                roomJson.put("acStatus", room.getAc_status());
                roomJson.put("currentTemperature", room.getCurrent_temperature());
                roomJson.put("targetTemperature", room.getTarget_temperature());
                roomJson.put("speed", room.getSpeed());
                roomJson.put("totalAirCost", room.getTotal_air_cost());
                roomJson.put("mode", room.getMode());
                jsonArray.add(roomJson);
            }
        }

        return jsonArray.toString();
    }

    @PostMapping("/all_room")
    String allRoom() {
        JSONArray jsonArray = new JSONArray();
        synchronized (PublicData.class) {
            for (Room room : PublicData.totalRoomList.values()) {
                if(room.getCustomer_id()!=null) {
                    JSONObject roomJson = new JSONObject();
                    roomJson.put("room_id", room.getRoom_id());

                    roomJson.put("name", room.getCustomer_id());

                    roomJson.put("password", "1");
                    jsonArray.add(roomJson);
                }
            }
        }

        return jsonArray.toString();
    }


    @PostMapping("/request_room")
    String getFirstFreeRoom(@RequestBody String data_string) {
        JSONObject jsonObject = JSONObject.parseObject(data_string);
        String name = jsonObject.getString("name");
        synchronized (PublicData.class) {
            JSONObject roomJson = new JSONObject();
            boolean flag = false;
            for (Room room : PublicData.totalRoomList.values()) {
                if (!room.isStatus()) {
                    flag = true;
                    room.setCustomer_id(name);
                    room.setStatus(true);
                    roomJson.put("room_id", room.getRoom_id());
                    roomJson.put("password", "1");
                    room.setStart_time(ACManager.currtimer);
                    return roomJson.toString();
                }
            }
            int code;
            String msg;
            if(flag){
                code = 200;
                msg = "success";
                roomJson.put("code", code);
                roomJson.put("msg", msg);
                return roomJson.toString();
            }else{
                code = 400;
                msg = "fail";
                roomJson.put("code", code);
                roomJson.put("msg", msg);
                return roomJson.toString();
            }
        }
    }
    @PostMapping("/checkout")
    ResponseEntity<InputStreamResource> checkout(@RequestBody String data_string) throws FileNotFoundException {
        JSONObject jsonObject = JSON.parseObject(data_string);
        int room_id = jsonObject.getInteger("room_id");
        Room room;
        synchronized (PublicData.class) {
            room = PublicData.totalRoomList.get(room_id);
            if(room!=null) {
                room.setStatus(false);
                room.setEnd_time(ACManager.currtimer);
            }
        }
            showAllRoomDetailedRecords(room_id);
            PublicData.resetRoom(PublicData.temp,room_id);
            File file = new File("D:\\ideaProject\\Server\\record"+room_id+".xlsx");
            if (!file.exists()) {
                throw new FileNotFoundException("File not found");
            }
            InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=" + file.getName())
                    .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
                    .body(resource);

    }
    private void showAllRoomDetailedRecords(int room_id) {
        int rowNumber = 0;
        int rowNumber1 =0;
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("详单");
        Sheet sheet1 = workbook.createSheet("账单");
        Row row = sheet.createRow(rowNumber);
        Room r;
        synchronized (PublicData.class) {
            r = PublicData.totalRoomList.get(room_id);
        }
            Cell cell00 = row.createCell(0);
            cell00.setCellValue("房间ID");
            Cell cell01 = row.createCell(1);
            cell01.setCellValue(r.getRoom_id());

            Row row1 = sheet.createRow(++rowNumber);
            Cell cell10 = row1.createCell(0);
            cell10.setCellValue("请求的时间");
            Cell cell11 = row1.createCell(1);
            cell11.setCellValue(r.request_time);

            Row row2 = sheet.createRow(++rowNumber);
            Cell cell20 = row2.createCell(0);
            cell20.setCellValue("风速");
            Cell cell21 = row2.createCell(1);
            cell21.setCellValue("风速对应的速率");
            Cell cell22 = row2.createCell(2);
            cell22.setCellValue("开始服务的时间");
            Cell cell23 = row2.createCell(3);
            cell23.setCellValue("结束服务的时间");
            Cell cell24 = row2.createCell(4);
            cell24.setCellValue("该风速的服务时间");
            Cell cell25 = row2.createCell(5);
            cell25.setCellValue("该段服务消费");

            r.makeDetailedRecord();
            for (Record record : r.recordList) {
                //record.printRecord();
                Row row3 = sheet.createRow(++rowNumber);
                Cell cell30 = row3.createCell(0);
                cell30.setCellValue(record.speed);
                Cell cell31 = row3.createCell(1);
                cell31.setCellValue(record.cost_rate);
                Cell cell32 = row3.createCell(2);
                cell32.setCellValue(record.start_time);
                Cell cell33 = row3.createCell(3);
                cell33.setCellValue(record.end_time);
                Cell cell34 = row3.createCell(4);
                cell34.setCellValue(record.server_time);
                Cell cell35 = row3.createCell(5);
                cell35.setCellValue(record.cur_cost);
            }

            Row r1ow = sheet1.createRow(rowNumber1);
            Cell cel100 = r1ow.createCell(0);
            cel100.setCellValue("房间ID");
            Cell cel101 = r1ow.createCell(1);
            cel101.setCellValue(r.getRoom_id());

            Row r2ow = sheet1.createRow(++rowNumber1);
            Cell cel200 = r2ow.createCell(0);
            cel200.setCellValue("办理入住时间");
            Cell cel201 = r2ow.createCell(1);
            cel201.setCellValue(r.start_time);

            Row r3ow = sheet1.createRow(++rowNumber1);
            Cell cel300 = r3ow.createCell(0);
            cel300.setCellValue("结账离开时间");
            Cell cel301 = r3ow.createCell(1);
            cel301.setCellValue(r.end_time);

            Row r4ow = sheet1.createRow(++rowNumber1);
            Cell cel400 = r4ow.createCell(0);
            cel400.setCellValue("总费用");
            Cell cel401 = r4ow.createCell(1);
            cel401.setCellValue(r.getTotal_air_cost()+r.getTotal_cost());

        try (FileOutputStream fileOut = new FileOutputStream("D:\\ideaProject\\Server\\record"+room_id+".xlsx")) {
            workbook.write(fileOut);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public ByteArrayOutputStream convertExcelToPdf(InputStream excelInputStream) throws Exception {
        // Load Excel file
        Workbook workbook = new XSSFWorkbook(excelInputStream);
        Sheet sheet = workbook.getSheetAt(0);

        // Create PDF document
        ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
        PdfWriter writer = new PdfWriter(pdfOutputStream);
        PdfDocument pdfDoc = new PdfDocument(writer);
        Document document = new Document(pdfDoc);

        // Iterate through Excel rows and convert to PDF
        for (Row row : sheet) {
            StringBuilder rowData = new StringBuilder();
            row.forEach(cell->rowData.append(cell.toString()).append(" "));
            document.add(new Paragraph(rowData.toString()));
        }

        document.close();
        workbook.close();

        return pdfOutputStream;
    }

}
